home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
c
/
bc_ti.zip
/
TI445.ASC
< prev
next >
Wrap
Text File
|
1992-02-25
|
20KB
|
793 lines
PRODUCT : TURBO C NUMBER : 445
VERSION : 1.0 & 1.5
OS : DOS 2.X & 3.X
DATE : OCTOBER 5, 1988 PAGE : 1/13
TITLE : INTERRUPT DRIVEN SERIAL COMMUNICATIONS
/*-------------------------------------------------------------*
SERIAL.C
The following code shows how to take advantage of some of
the Turbo C extensions to the C language to do asynchronous
communications without having to write supporting assembly-
language routines.
This program bypasses the less-than-adequate PC BIOS com-
munications routines and installs a serial interrupt handler.
Direct access to PC hardware allows the program to run at
faster baud rates and eliminates the need for the main
program to continuously poll the serial port for data; thus,
implementing background communications. Data that enters
the serial port is stored in a circular buffer.
* Compile this program with Test Stack Overflow OFF.
*-------------------------------------------------------------*/
#include "serial.h"
#include <dos.h>
#include <conio.h>
#include <stdio.h>
#include <string.h>
#define VERSION 0x0101
#define FALSE 0
#define TRUE (!FALSE)
#define NOERROR 0 /* No error */
#define BUFOVFL 1 /* Buffer overflowed */
#define ESC 0x1B /* ASCII Escape character */
#define ASCII 0x007F /* Mask ASCII characters */
#define SBUFSIZ 0x4000 /* Serial buffer size */
int SError = NOERROR;
int portbase = 0;
void interrupt(*oldvects[2])();
static char ccbuf[SBUFSIZ];
unsigned int startbuf = 0;
unsigned int endbuf = 0;
PRODUCT : TURBO C NUMBER : 445
VERSION : 1.0 & 1.5
OS : DOS 2.X & 3.X
DATE : OCTOBER 5, 1988 PAGE : 2/13
TITLE : INTERRUPT DRIVEN SERIAL COMMUNICATIONS
/* Handle communications interrupts and put them in ccbuf */
void interrupt com_int(void)
{
disable();
if ((inportb(portbase + IIR) & RX_MASK) == RX_ID)
{
if (((endbuf + 1) & SBUFSIZ - 1) == startbuf)
SError = BUFOVFL;
ccbuf[endbuf++] = inportb(portbase + RXR);
endbuf &= SBUFSIZ - 1;
}
/* Signal end of hardware interrupt */
outportb(ICR, EOI);
enable();
}
/* Output a character to the serial port */
int SerialOut(char x)
{
long int timeout = 0x0000FFFFL;
outportb(portbase + MCR, MC_INT | DTR | RTS);
/* Wait for Clear To Send from modem */
while ((inportb(portbase + MSR) & CTS) == 0)
if (!(--timeout))
return (-1);
timeout = 0x0000FFFFL;
/* Wait for transmitter to clear */
while ((inportb(portbase + LSR) & XMTRDY) == 0)
if (!(--timeout))
return (-1);
disable();
outportb(portbase + TXR, x);
enable();
return (0);
}
PRODUCT : TURBO C NUMBER : 445
VERSION : 1.0 & 1.5
OS : DOS 2.X & 3.X
DATE : OCTOBER 5, 1988 PAGE : 3/13
TITLE : INTERRUPT DRIVEN SERIAL COMMUNICATIONS
/* Output a string to the serial port */
void SerialString(char *string)
{
while (*string)
SerialOut(*string++);
}
/* This routine returns the current value in the buffer */
int getccb(void)
{
int res;
if (endbuf == startbuf)
return (-1);
res = (int) ccbuf[startbuf++];
startbuf %= SBUFSIZ;
return (res);
}
/* Install our functions to handle communications */
void setvects(void)
{
oldvects[0] = getvect(0x0B);
oldvects[1] = getvect(0x0C);
setvect(0x0B, com_int);
setvect(0x0C, com_int);
}
/* Uninstall our vectors before exiting the program */
void resvects(void)
{
setvect(0x0B, oldvects[0]);
setvect(0x0C, oldvects[1]);
}
/* Turn on communications interrupts */
void i_enable(int pnum)
{
int c;
disable();
c = inportb(portbase + MCR) | MC_INT;
PRODUCT : TURBO C NUMBER : 445
VERSION : 1.0 & 1.5
OS : DOS 2.X & 3.X
DATE : OCTOBER 5, 1988 PAGE : 4/13
TITLE : INTERRUPT DRIVEN SERIAL COMMUNICATIONS
outportb(portbase + MCR, c);
outportb(portbase + IER, RX_INT);
c = inportb(IMR) & (pnum == COM1 ? IRQ4 : IRQ3);
outportb(IMR, c);
enable();
}
/* Turn off communications interrupts */
void i_disable(void)
{
int c;
disable();
c = inportb(IMR) | ~IRQ3 | ~IRQ4;
outportb(IMR, c);
outportb(portbase + IER, 0);
c = inportb(portbase + MCR) & ~MC_INT;
outportb(portbase + MCR, c);
enable();
}
/* Tell modem that we're ready to go */
void comm_on(void)
{
int c, pnum;
pnum = (portbase == COM1BASE ? COM1 : COM2);
i_enable(pnum);
c = inportb(portbase + MCR) | DTR | RTS;
outportb(portbase + MCR, c);
}
/* Go off-line */
void comm_off(void)
{
i_disable();
outportb(portbase + MCR, 0);
}
void initserial(void)
{
endbuf = startbuf = 0;
setvects();
PRODUCT : TURBO C NUMBER : 445
VERSION : 1.0 & 1.5
OS : DOS 2.X & 3.X
DATE : OCTOBER 5, 1988 PAGE : 5/13
TITLE : INTERRUPT DRIVEN SERIAL COMMUNICATIONS
comm_on();
}
void closeserial(void)
{
comm_off();
resvects();
}
/* Set the port number to use */
int SetPort(int Port)
{
int Offset, far *RS232_Addr;
switch (Port)
{ /* Sort out the base address */
case COM1 : Offset = 0x0000;
break;
case COM2 : Offset = 0x0002;
break;
default : return (-1);
}
RS232_Addr = MK_FP(0x0040, Offset); /* Find out where the
port is. */
if (*RS232_Addr == NULL) return (-1);/* If NULL, then port
not used. */
portbase = *RS232_Addr; /* Otherwise, set
portbase. */
return (0);
}
/* This routine sets the speed; will accept funny baud rates. */
/* Setting the speed requires that the DLAB be set on. */
int SetSpeed(int Speed)
{
char c;
int divisor;
if (Speed == 0) /* Avoid divide by zero */
return (-1);
else
PRODUCT : TURBO C NUMBER : 445
VERSION : 1.0 & 1.5
OS : DOS 2.X & 3.X
DATE : OCTOBER 5, 1988 PAGE : 6/13
TITLE : INTERRUPT DRIVEN SERIAL COMMUNICATIONS
divisor = (int) (115200L/Speed);
if (portbase == 0)
return (-1);
disable();
c = inportb(portbase + LCR);
outportb(portbase + LCR, (c | 0x80)); /* Set DLAB */
outportb(portbase + DLL, (divisor & 0x00FF));
outportb(portbase + DLH, ((divisor >> 8) & 0x00FF));
outportb(portbase + LCR, c); /* Reset DLAB */
enable();
return (0);
}
/* Set other communications parameters */
int SetOthers(int Parity, int Bits, int StopBit)
{
int setting;